#pragma once
#include<iostream>
#include<pthread.h>
#include<vector>
#include<unistd.h>
#include<time.h>
#include"Sem.hpp"
using namespace std;

int g_defualt_num = 5;//环形队列默认容量上限

template<class T>
class ringQueue
{ 
public:
    //构造：初始化数据
    ringQueue(int num = g_defualt_num)
        :_ring_queue(num)//这里是对vector对象进行构造：explicit vector (size_type n, const value_type& val = value_type());
        ,_num(num)
        ,p_step(0)//初始下标为0
        ,c_step(0)//初始下标为0
        ,space_sem(num)//构造信号量，初始时空间资源有num个
        ,data_sem(0)//构造信号量，初始时数据资源有0个
    { }

    //析构
    ~ringQueue()
    {}

    // 向环形队列中放入数据：生产者
    void push(const T &in)
    {
        // 申请信号量：预定空间资源
        space_sem.P();
        // 在特定位置生产数据
        _ring_queue[p_step++] = in;
        p_step %= _num; //[0,_num-1]
        // 生产成功，则意味着数据资源多了一个
        data_sem.V();
    }

    // 向环形队列中取出数据：消费者
    void pop(T *out)
    {
        // 申请信号量：预定数据资源
        data_sem.P();
        // 在特定位置消费数据
        *out = _ring_queue[c_step++];
        c_step %= _num;
        // 消费成功，则意味着空间资源多了一个
        space_sem.V();
    }

private:
    vector<T> _ring_queue;//环形队列：以数组的方式实现
    int _num;//环形队列容量上限
    int p_step;//生产者下标：在当前下标位置放入资源
    int c_step;//消费者下标：在当前下标位置取出资源
    Sem space_sem;//生产者信号量：空间资源
    Sem data_sem;//消费者信号量：数据资源
};